package org.ifilm.controller;

import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityExistsException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.ifilm.model.User;
import org.ifilm.model.UserRating;
import org.ifilm.service.UserService;
import org.ifilm.util.GeneralConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

/**
 * 
 * User Contoller. All requests about users will be here
 * 
 * @author Mustafa Genç
 * 
 */
@Controller
@RequestMapping("/user/**")
public class UserController {
	@Autowired
	private UserService userService;

	@RequestMapping(value = "/register", method = { RequestMethod.POST, RequestMethod.GET })
	public ModelAndView createUser(HttpServletRequest request, HttpServletResponse response) {
		ModelAndView result = new ModelAndView();

		User user = new User();
		user.setName(request.getParameter(GeneralConstants.userName));
		user.setSurname(request.getParameter(GeneralConstants.userSurname));
		user.setEmail(request.getParameter(GeneralConstants.userEmail));
		// TODO : password should be encrypted
		user.setPassword(request.getParameter(GeneralConstants.userPassword));
		user.setCreationTime(new Date());
		
		// TODO : also login??
		User createdUser = null;
		try {
			createdUser = userService.createUser(user);
		} catch (EntityExistsException e) {
			request.setAttribute("error", 1);
			result.setViewName("/registerUser.jsp");
		}

		if (createdUser != null) {
			request.setAttribute(GeneralConstants.user, createdUser);
			result.setViewName("/index.jsp");
		}

		return result;
	}

	@RequestMapping(value = "/login", method = { RequestMethod.POST, RequestMethod.GET })
	public ModelAndView login(HttpServletRequest request, HttpServletResponse response) {
		ModelAndView result = new ModelAndView();

		HttpSession session = request.getSession();

		String email = request.getParameter(GeneralConstants.userEmail);
		String password = request.getParameter(GeneralConstants.userPassword);

		User loggedUser = userService.getUser(email, password);

		if (loggedUser != null) {
			session.setAttribute(GeneralConstants.user, loggedUser);
			result.setViewName("/project/listProjects.do?page=1&max=" + GeneralConstants.MAXIMUM_PROJECT_PAGINATION);
		} else {
			result.setViewName("/index.jsp");
		}

		return result;
	}
	
	@RequestMapping(value = "/rate", method = {RequestMethod.POST, RequestMethod.GET})
	public ResponseEntity<Map<String, Object>> rateUser(@RequestParam(value = "userId") Long userId, @RequestParam(value = "rate") Integer rate,
			HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Map<String, Object> responseBody = new HashMap<String, Object>();
		
		User loggedUser = getLoggedUser(request);
		
		if (loggedUser != null) {
			User user = userService.getUserById(userId);
			
			UserRating oldRating =  userService.getUserRate(userId, loggedUser);
			
			if (oldRating == null) {
				UserRating userRating = new UserRating();
				userRating.setRate(rate);
				userRating.setRatedUser(user);
				userRating.setRater(loggedUser);
				
				userService.rateUser(userRating);
			} else {
				userService.updateRate(user, oldRating, rate);
			}
			
			responseBody.put("rate", user.getAverageRate());
		}
		
		return new ResponseEntity<Map<String, Object>>(responseBody, HttpStatus.OK);
	}
	
	@RequestMapping(value = "/getUser.do", method = { RequestMethod.POST, RequestMethod.GET })
	public ModelAndView getUser(@RequestParam(value = "userId") Long userId, HttpServletRequest request, HttpServletResponse response) {
		ModelAndView result = new ModelAndView();

		User user = userService.getUserById(userId);

		if (user != null) {
			result.setViewName("/userProfile.jsp");
			result.addObject(GeneralConstants.profileUser, user);
			result.addObject(userId);
			UserRating userRating = userService.getUserRate(userId, getLoggedUser(request));
			if (userRating != null) {
				result.addObject("rate", userRating.getRate());
			} else {
				result.addObject("rate", 0);
			}
		}

		return result;
	}

	@RequestMapping(value = "/editUser", method = { RequestMethod.POST, RequestMethod.GET })
	public ModelAndView editUser(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		ModelAndView result = new ModelAndView();

		User loggedUser = getLoggedUser(request);

		if (loggedUser != null) {
			String userName = request.getParameter(GeneralConstants.userName);
			if (StringUtils.isNotBlank(userName)) {
				loggedUser.setName(userName);
			}
			
			String userSurname = request.getParameter(GeneralConstants.userSurname);
			if (StringUtils.isNotBlank(userSurname)) {
				loggedUser.setSurname(userSurname);
			}
			
			String userProfessionalInfo = request.getParameter(GeneralConstants.userProfessionalInfo);
			if (StringUtils.isNotBlank(userProfessionalInfo)) {
				loggedUser.setProfessionalInfo(userProfessionalInfo);
			}
			
			String userAbout = request.getParameter(GeneralConstants.userAbout);
			if (StringUtils.isNotBlank(userAbout)) {
				loggedUser.setAbout(userAbout);
			}
			
			String userGender = request.getParameter(GeneralConstants.userGender);
			if (StringUtils.isNotBlank(userGender)) {
				loggedUser.setGender(userGender);
			}
			
			String userBirthday = request.getParameter(GeneralConstants.userBirthday);
			if (StringUtils.isNotBlank(userBirthday)) {
				int year = Calendar.getInstance().get(Calendar.YEAR);	
				try{
					int prevyear =Integer.parseInt(userBirthday.substring(0,4));
					int age = year -prevyear;
					if (age>0) {					
						loggedUser.setAge(age);					
					}
				}
				catch(NumberFormatException e){}
					
					loggedUser.setBirthdate(userBirthday);
			}
			
			String userPhone = request.getParameter(GeneralConstants.userPhone);
			if (StringUtils.isNotBlank(userPhone)) {
				loggedUser.setPhone(userPhone);
			}
			
			String userThumbnailUrl = request.getParameter(GeneralConstants.userThumbnailUrl);
			if (StringUtils.isNotBlank(userThumbnailUrl)) {
				loggedUser.setThumbnailUrl(userThumbnailUrl);
			}
			
			String weight = request.getParameter(GeneralConstants.userWeight);
			if (StringUtils.isNotBlank(weight)) {
				try {
					loggedUser.setWeight(Integer.parseInt(weight));
				} catch (NumberFormatException e) {}
			}
			
			String height = request.getParameter(GeneralConstants.userHeight);
			if (StringUtils.isNotBlank(height)) {
				try {
					loggedUser.setHeight(Integer.parseInt(height));
				} catch (NumberFormatException e) {}
			}
			
			String hairColor = request.getParameter(GeneralConstants.userHairColor);
			if (StringUtils.isNotBlank(hairColor)) {
				loggedUser.setHairColor(hairColor);
			}
			
			String eyeColor = request.getParameter(GeneralConstants.userEyeColor);
			if (StringUtils.isNotBlank(eyeColor)) {
				loggedUser.setEyeColor(eyeColor);
			}
			
			
			
			String userType = request.getParameter(GeneralConstants.userType);
			if (StringUtils.isNotBlank(userType)) {
				userType = StringUtils.remove(userType, "[");
				userType = StringUtils.remove(userType, "]");
				userType = StringUtils.remove(userType, " ");
				
				String[] userTypes = userType.split(",");
				
				List<String> userTypeList = Arrays.asList(userTypes);
				
				loggedUser.setUserType(userTypeList);
			}
			
			loggedUser.setUpdateTime(new Date());
			
			userService.editUser(loggedUser);
			
			result.addObject(GeneralConstants.profileUser, loggedUser);
			result.setViewName("/userProfile.jsp");
			result.addObject(GeneralConstants.userId,loggedUser.getId());
			request.getSession().setAttribute(GeneralConstants.user, loggedUser);
		}
		
		return result;
	}
	
	@RequestMapping(value = "/logout", method = { RequestMethod.POST, RequestMethod.GET })
	public void logout(HttpServletRequest request, HttpServletResponse response) {
		HttpSession session = request.getSession();

		session.invalidate();
	}
	
	@RequestMapping(value = "/getLoggedUserTypes", method = {RequestMethod.POST, RequestMethod.GET})
	public ResponseEntity<Map<String, Object>> getUserTypes(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Map<String, Object> responseBody = new HashMap<String, Object>();
		
		responseBody.put("types", getLoggedUser(request).getUserType());
		
		return new ResponseEntity<Map<String, Object>>(responseBody, HttpStatus.OK);
	}
	
	@RequestMapping(value = "/getUserTypesById", method = {RequestMethod.POST, RequestMethod.GET})
	public ResponseEntity<Map<String, Object>> getUserTypesById(@RequestParam(value = "userId") Long userId, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Map<String, Object> responseBody = new HashMap<String, Object>();
		
		User user = userService.getUserById(userId);
		
		responseBody.put("types", user.getUserType());
		
		return new ResponseEntity<Map<String, Object>>(responseBody, HttpStatus.OK);
	}
	
	@RequestMapping(value = "/follow", method = { RequestMethod.POST, RequestMethod.GET })
	public void followUser(@RequestParam Long followingId, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		User loggedUser = getLoggedUser(request);
		User followerUser = userService.getUserById(loggedUser.getId());
		User followingUser = userService.getUserById(followingId);
		
		userService.followUser(followerUser, followingUser);
	}
	
	@RequestMapping(value = "/unfollow", method = { RequestMethod.POST, RequestMethod.GET })
	public void unfollowUser(@RequestParam Long followingId, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		User loggedUser = getLoggedUser(request);
		User followerUser = userService.getUserById(loggedUser.getId());
		User followingUser = userService.getUserById(followingId);
		
		userService.unfollowUser(followerUser, followingUser);
	}
	
	@RequestMapping(value = "/getFollowing", method = {RequestMethod.POST, RequestMethod.GET})
	public ResponseEntity<Map<String, Object>> getFollowing(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		Map<String, Object> responseBody = new HashMap<String, Object>();
		
		User loggedUser = getLoggedUser(request);

		responseBody.put("users", loggedUser.getFollowingUsers());
		
		return new ResponseEntity<Map<String, Object>>(responseBody, HttpStatus.OK);
	}
	
	private User getLoggedUser(HttpServletRequest request) {
		HttpSession session = request.getSession();
		
		return (User) session.getAttribute(GeneralConstants.user);
	}
}